/*
 * DFCImage.cpp
 *
 *  Created on: 09/01/2011
 *      Author: Danilo
 */

#include "DFCImage.h"

#include "DFCMain.h"
#include "DFCVideo.h"
#include "SDL/SDL_image.h"

//------------------------------------------------
// Nome: DFCImage()
// Desc: Construtor padr�o
// Pams: nenhum
//------------------------------------------------
DFCImage::DFCImage()
{
    // Inicializa o numero de refer�ncias para a imagem em zero
    sReferences = 0;
    // Inicializa a superf�cie da SDL em nulo
    p_Surface = NULL;
    // Inicializa o ponteiro para o DFCVideo em nulo
    pr_Video = NULL;
}

//------------------------------------------------
// Nome: DFCImage(DFCVideo *videoRef)
// Desc: Construtor com argumento
// Pams: videoRef: ponteiro com referencia para DFCVideo
//------------------------------------------------
DFCImage::DFCImage(DFCVideo *videoRef)
{
    // Inicializa o numero de refer�ncias para a imagem em zero
    sReferences = 0;
    // Inicializa a superf�cie da SDL em nulo
    p_Surface = NULL;
    // Inicializa o ponteiro para o DFCVideo em nulo
    pr_Video = videoRef;
}

//------------------------------------------------
// Nome: ~DFCImage()
// Desc: Destrutor padr�o
// Pams: nenhum
//------------------------------------------------
DFCImage::~DFCImage()
{
    // Libera a classe da mem�ria
    Release();
}

//------------------------------------------------
// Nome: Release()
// Desc: Descarrega a imagem da mem�ria
// Pams: nenhum
//------------------------------------------------
bool DFCImage::Release()
{
    if (p_Surface)
    {
        SDL_FreeSurface(p_Surface);
        p_Surface = NULL;
    }
    ClearFrames();

    return true;
}

//------------------------------------------------
// Nome: LoadFromFile(const char *cp_chFileName)
// Desc: Carrega a imagem do arquivo
// Pams: cp_chFileName: nome do arquivo da imagem a ser carregada
//------------------------------------------------
bool DFCImage::LoadFromFile(const char *cp_chFileName)
{
    Release();
    if (cp_chFileName)
    {
        FileName = cp_chFileName;

        SDL_Surface* p_SurfaceTemp = IMG_Load(cp_chFileName);

        if (p_SurfaceTemp)
        {
            p_Surface = SDL_DisplayFormat(p_SurfaceTemp);

            SDL_FreeSurface(p_SurfaceTemp);
        }

        Size.setX(p_Surface->w);
        Size.setY(p_Surface->h);

        if (!p_Surface)
        {
            return false;
        }
    }
    return true;
}

//------------------------------------------------
// Nome: SetColorKey(unsigned int uiColorKey)
// Desc: Indica a cor de transpar�ncia
// Pams: uiRed: c�digo do Red (RGB)
//       uiGreen: c�digo do Green (RGB)
//       uiBlue: c�digo do Blue (RGB)
//------------------------------------------------
bool DFCImage::SetColorKey(Uint8 uiRed, Uint8 uiGreen, Uint8 uiBlue)
{
    ColorKey = SDL_MapRGB(p_Surface->format, uiRed, uiGreen, uiBlue);
    if (SDL_SetColorKey(p_Surface, SDL_SRCCOLORKEY, ColorKey) == 0)
    {
        return true;
    }

    return false;
}

//------------------------------------------------
// Nome: Reload()
// Desc: Recarrega o arquivo de imagem
// Pams: nenhum
//------------------------------------------------
void DFCImage::Reload()
{
    string Name = FileName;
    DFCVector v = FrameSize;
    FrameSize.fx++;
    LoadFromFile(Name.c_str());
    SetFrameSize(v);
}

//------------------------------------------------
// Nome: SetFrameSize(const DFCVector &cSizeParam)
// Desc: Indica o tamanho do frame de anima��o da imagem
// Pams: cSizeParam: DFCVector com as dimens�es do frame
//------------------------------------------------
void DFCImage::SetFrameSize(const DFCVector &cSizeParam)
{
    if(FrameSize != cSizeParam)
    {
        FrameSize = cSizeParam;
        FrameSize.setX((FrameSize.fx > Size.fy) ? Size.fx : FrameSize.fx);
        FrameSize.setY((FrameSize.fy > Size.fy) ? Size.fy : FrameSize.fy);
        ClearFrames();

        if(FrameSize.fx >= 1.0f && FrameSize.fy >= 1.0f)
        {
            int iSizeX = ((int)Size.fx) / ((int)FrameSize.fx);
            int iSizeY = ((int)Size.fy) / ((int)FrameSize.fy);

            for (int j = 0; j < iSizeY; j++)
            {
                for (int i = 0; i < iSizeX; i++)
                {
                    DFCFrame *p_Frame = new DFCFrame();
                    p_Frame->iTop       = j*(int)FrameSize.fy;
                    p_Frame->iBottom    = (j+1)*(int)FrameSize.fy;
                    p_Frame->iLeft      = i*(int)FrameSize.fx;
                    p_Frame->iRight     = (i+1)*(int)FrameSize.fx;
                    Frames.push_back(p_Frame);
                }
            }
        }
    }
}

//------------------------------------------------
// Nome: ClearFrames()
// Desc: Apaga os frames de anima��o da imagem
// Pams: nenhum
//------------------------------------------------
void DFCImage::ClearFrames()
{
    for (int i = (int)Frames.size() - 1; i >= 0; i--)
    {
        delete Frames[i];
    }
    Frames.clear();
}

//------------------------------------------------
// Nome: DrawImage(DFCVector offset)
// Desc: Pinta a imagem na tela
// Pams: cOffset: DFCVector com a posi��o onde a imagem deve ser pintada
//------------------------------------------------
bool DFCImage::DrawImage(DFCVector &cOffset)
{
    SDL_Rect rect;
    rect.x = cOffset.fx;
    rect.y = cOffset.fy;
    rect.h = 0;
    rect.w = 0;

    if (SDL_BlitSurface(p_Surface, NULL, pr_Video->p_Screen, &rect) == -1)
    {
        return false;
    }

    return true;
}

//------------------------------------------------
// Nome: DrawFrame(int iFrame, DFCVector offset)
// Desc: Pinta um frame desta imagem na tela
// Pams: iFrame: frame a ser desenhado
//       cOffset: DFCVector com a posi��o onde a imagem deve ser pintada
//------------------------------------------------
bool DFCImage::DrawFrame(int iFrame, DFCVector &cOffset)
{
    SDL_Rect srcrect;
    SDL_Rect dstrect;

    DFCFrame* p_SrcFrame = Frames[iFrame];
    srcrect.x = p_SrcFrame->iLeft;
    srcrect.y = p_SrcFrame->iTop;
    srcrect.w = p_SrcFrame->GetWidth();
    srcrect.h = p_SrcFrame->GetHeight();

    dstrect.x = cOffset.fx;
    dstrect.y = cOffset.fy;
    dstrect.w = 0;
    dstrect.h = 0;

    if (SDL_BlitSurface(p_Surface, &srcrect, pr_Video->p_Screen, &dstrect) == -1)
    {
        return false;
    }

    return true;
}
